#!/bin/bash

# 串口使用情况检查脚本

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 帮助信息
show_help() {
    cat << EOF
用法: $0 [选项] [串口设备]

选项:
    -a, --all          检查所有串口设备
    -p, --port PORT    检查指定串口设备 (如: /dev/ttyUSB0, /dev/ttyS0)
    -l, --list         列出所有可用的串口设备
    -m, --monitor      实时监控串口状态变化
    -h, --help         显示此帮助信息

示例:
    $0 -a                    # 检查所有串口
    $0 -p /dev/ttyUSB0      # 检查指定串口
    $0 -l                   # 列出所有串口设备
    $0 -m                   # 实时监控串口状态

EOF
}

# 检查命令是否存在
check_command() {
    if ! command -v "$1" &> /dev/null; then
        echo -e "${RED}错误: 未找到 $1 命令，请先安装${NC}"
        return 1
    fi
    return 0
}

# 列出所有串口设备
list_serial_ports() {
    echo -e "${BLUE}=== 可用的串口设备 ===${NC}"
    
    local found=0
    
    # 检查物理串口
    for port in /dev/ttyS[0-9]*; do
        if [ -c "$port" ]; then
            echo -e "物理串口: ${GREEN}$port${NC}"
            found=1
        fi
    done
    
    # 检查USB串口
    for port in /dev/ttyUSB[0-9]*; do
        if [ -c "$port" ]; then
            echo -e "USB串口:  ${GREEN}$port${NC}"
            found=1
        fi
    done
    
    # 检查ACM设备（如Arduino）
    for port in /dev/ttyACM[0-9]*; do
        if [ -c "$port" ]; then
            echo -e "ACM设备:  ${GREEN}$port${NC}"
            found=1
        fi
    done
    
    if [ $found -eq 0 ]; then
        echo -e "${YELLOW}未找到任何串口设备${NC}"
    fi
}

# 检查串口设备详细信息
check_port_details() {
    local port=$1
    
    if [ ! -e "$port" ]; then
        echo -e "${RED}错误: 设备 $port 不存在${NC}"
        return 1
    fi
    
    if [ ! -c "$port" ]; then
        echo -e "${RED}错误: $port 不是字符设备${NC}"
        return 1
    fi
    
    echo -e "${BLUE}=== 串口设备: $port ===${NC}"
    
    # 显示设备权限和属性
    local device_info=$(ls -l "$port")
    echo -e "设备信息: $device_info"
    
    # 解析设备信息
    local major_minor=$(ls -l "$port" | awk '{print $5","$6}')
    local permissions=$(ls -l "$port" | awk '{print $1}')
    local owner_group=$(ls -l "$port" | awk '{print $3":"$4}')
    
    echo -e "设备号:   $major_minor"
    echo -e "权限:     $permissions"
    echo -e "属主:     $owner_group"
    
    # 检查是否被使用
    check_port_usage "$port"
    
    echo ""
}

# 检查串口使用情况
check_port_usage() {
    local port=$1
    
    # 使用 lsof 检查
    if check_command lsof; then
        local lsof_result=$(lsof "$port" 2>/dev/null)
        if [ -n "$lsof_result" ]; then
            echo -e "${YELLOW}*** 设备正在被使用 ***${NC}"
            echo "$lsof_result" | while read -r line; do
                if [[ $line == COMMAND* ]]; then
                    echo -e "${GREEN}$line${NC}"
                else
                    echo "$line"
                fi
            done
        else
            echo -e "${GREEN}设备未被使用${NC}"
        fi
    fi
    
    # 使用 fuser 检查
    if check_command fuser; then
        local fuser_result=$(fuser -v "$port" 2>/dev/null)
        if [ -n "$fuser_result" ]; then
            echo -e "${YELLOW}*** fuser 检测结果 ***${NC}"
            echo "$fuser_result"
        fi
    fi
    
    # 检查 /proc 文件系统
    local proc_usage=$(find /proc/*/fd -lname "*$(basename "$port")*" -exec ls -l {} + 2>/dev/null | head -5)
    if [ -n "$proc_usage" ]; then
        echo -e "${YELLOW}*** 进程文件描述符 ***${NC}"
        echo "$proc_usage"
    fi
}

# 检查所有串口
check_all_ports() {
    echo -e "${BLUE}=== 检查所有串口设备 ===${NC}"
    echo ""
    
    local found=0
    
    # 检查所有类型的串口设备
    for pattern in "/dev/ttyS*" "/dev/ttyUSB*" "/dev/ttyACM*"; do
        for port in $pattern; do
            if [ -c "$port" ]; then
                check_port_details "$port"
                found=1
            fi
        done
    done
    
    if [ $found -eq 0 ]; then
        echo -e "${YELLOW}未找到任何串口设备${NC}"
    fi
}

# 实时监控串口状态
monitor_serial_ports() {
    echo -e "${BLUE}=== 串口状态监控 (按 Ctrl+C 退出) ===${NC}"
    echo -e "监控开始时间: $(date)"
    echo ""
    
    # 保存初始状态
    declare -A initial_state
    for pattern in "/dev/ttyS*" "/dev/ttyUSB*" "/dev/ttyACM*"; do
        for port in $pattern; do
            if [ -c "$port" ]; then
                initial_state["$port"]=1
            fi
        done
    done
    
    while true; do
        clear
        echo -e "${BLUE}=== 串口状态监控 - $(date) ===${NC}"
        echo ""
        
        # 检查设备变化
        declare -A current_state
        for pattern in "/dev/ttyS*" "/dev/ttyUSB*" "/dev/ttyACM*"; do
            for port in $pattern; do
                if [ -c "$port" ]; then
                    current_state["$port"]=1
                    if [ -z "${initial_state[$port]}" ]; then
                        echo -e "${GREEN}[新增] $port${NC}"
                    fi
                fi
            done
        done
        
        # 检查消失的设备
        for port in "${!initial_state[@]}"; do
            if [ -z "${current_state[$port]}" ]; then
                echo -e "${RED}[移除] $port${NC}"
            fi
        done
        
        echo ""
        
        # 显示当前状态
        for port in "${!current_state[@]}"; do
            echo -n "设备: $port - "
            if lsof "$port" &>/dev/null; then
                echo -e "${RED}使用中${NC}"
                lsof "$port" | tail -1 | awk '{print "  进程:", $1, "PID:", $2, "用户:", $3}'
            else
                echo -e "${GREEN}空闲${NC}"
            fi
        done
        
        initial_state=()
        for key in "${!current_state[@]}"; do
            initial_state["$key"]=1
        done
        
        echo ""
        echo -e "按 ${YELLOW}Ctrl+C${NC} 退出监控"
        sleep 5
    done
}

# 主函数
main() {
    # 检查必要命令
    if ! check_command ls && ! check_command lsof && ! check_command fuser; then
        echo -e "${RED}错误: 缺少必要的系统命令${NC}"
        exit 1
    fi
    
    # 参数解析
    if [ $# -eq 0 ]; then
        show_help
        exit 0
    fi
    
    case "$1" in
        -a|--all)
            check_all_ports
            ;;
        -p|--port)
            if [ -z "$2" ]; then
                echo -e "${RED}错误: 请指定串口设备${NC}"
                exit 1
            fi
            check_port_details "$2"
            ;;
        -l|--list)
            list_serial_ports
            ;;
        -m|--monitor)
            monitor_serial_ports
            ;;
        -h|--help)
            show_help
            ;;
        *)
            echo -e "${RED}错误: 未知选项 $1${NC}"
            show_help
            exit 1
            ;;
    esac
}

# 脚本入口
main "$@"